﻿/*
说明：对图片缩放操作的封装
作者：张雁鸿
时间：2010-5-23
版本：0.2
依赖：jQuery1.4.2 and jQueryUI.18.1

历史：
V0.2 
1、 在缩放过程中不断修正长宽比。
2、 增加最大放大倍数及图片的最小像素选项。


Description: picture zoom function
Author: Zhang Yanhong
Date: 2010-5-23
Version: 0.2

History:


Depend on: 
1 jQuery1.4.2
2 jQueryUI.18.1
3 jqMousewheel.js
4 StringExtend.js
Sample:
$(".container").piczoom({ image: "../sample.png", desc: "图片",maxscale:50,minpixel:150 })
//maxscale:允许放大的最大比例
//minpixel:允许的最小像素
*/

(function($) {
    $.images = [];
    $.fn.extend({
        //图片缩放功能
        piczoom: function(option) {
            //默认的设置
            var defaults = {
                image: "",
                desc: "",
                maxscale: 50, //最大放大倍数
                minpixel:50 //图片的最小像素
            };
            var setting = {}; //= defaults;
            setting = $.extend(setting, defaults, option);

            $(this).each(function() {
                $.images.push($(this));
                //××××功能按钮组定义开始
                var btnGroup;
                btnGroup = $("<span>", {
                    "class": "ui-widget-header ui-corner-all button",
                    style: "position: absolute;font-size: 10px;margin: 3px;z-index:1;"
                });
                //---重置按钮定义开始
                var reset = $("<a></a>").html("重置").button({ icons: { primary: "ui-icon-refresh"} });
                btnGroup.append(reset);
                reset.click(function() {
                    $(this).parent().parent().data("ref").reset();
                });
                //---重置按钮定义结束
                $(this).append(btnGroup);
                //××××功能按钮组定义结束

                //---图片定义开始
                var imgCon = $("<div>");
                imgCon.attr("style", "background-color:black;overflow: hidden;width: 100%;height: 100%;left: 0px;top: 0px;");
                var img;
                img = $("<img>", {
                    "class": "",
                    style: "position:relative;",
                    //src: setting.image,
                    alt: setting.desc
                }).load(function() {
                    var w = $(this).width();
                    var h = $(this).height();
                    $(this).parent().parent().data("ref").originalSize.w = w;
                    $(this).parent().parent().data("ref").originalSize.h = h;
                    $(this).parent().parent().data("ref").originalSize.ratio = h / w;
                });
                imgCon.append(img);
                img.attr("src", setting.image);
                imgCon.css("position", "absolute");
                $(this).append(imgCon);
                imgCon.draggable({ //鼠标平移
                    start: function(e, ui) {
                        //alert(this.id);
                        $(this).addClass("down");
                        $(this).removeClass("up");
                    },
                    stop: function(e, ui) {
                        $(this).addClass("up");
                        $(this).removeClass("down");
                        var pic = $("img", this);
                        var off = pic.offset();
                        $(this).parent().data("ref").pan(off);
                    }
                }).mouseover(function(event) {
                    $(this).parent().data("ref").mouse = true;
                }).mouseout(function(event) {
                    $(this).parent().data("ref").mouse = false;
                }).mousewheel(function(event, delta) { //鼠标缩放
                    //alert(delta);
                    if (delta == undefined) return; //chrome多一次无参触发
                    //alert(delta);
                    var z = 60; //放大倍数
                    if (delta > 0) {
                        z = 1 + z * delta / 100;
                    }
                    else {
                        z = 1 + z * delta / 200;
                        if (z < 0) {
                            z = 1 - Math.floor(199 / 60) * 60 / 200;
                        }
                    }
                    $(this).parent().data("ref").zoom(event, z);
                });
                //--图片定义结束

                //---鼠标移动定义
                $(document).keydown(function(event) {
                    var dx = 0, dy = 0;
                    var interval = 1;
                    switch (event.keyCode) {
                        case 37:
                            dx -= interval;
                            break;
                        case 38:
                            dy -= interval;
                            break;
                        case 39:
                            dx += interval;
                            break;
                        case 40:
                            dy += interval;
                            break;
                    }
                    $.each($.images, function(i, obj) {

                        if (obj.data("ref").mouse) {
                            obj.data("ref").pan(dx, dy);
                        }
                    })
                });
                //---定义需要缓存的内容
                var ref = {
                    mouse: false, //鼠标是否在该元素上
                    img: imgCon, //图片容器的引用
                    parent: $(this), //用户用于显示的图片的对象
                    originalSize: { w: img.attr("width"), h: img.attr("height"), ratio: 1 }, //图片的原始尺寸-ratio=h/w（高宽比）
                    currentSize: { w: 1, h: 1, ratio: 1 }, //当前图像尺寸
                    scale: 1, //缩放比例
                    maxscale: setting.maxscale, //允许的最大比率
                    minpixel: setting.minpixel, //允许缩小的最小像素
                    winresize: function() {
                        this.img.height(this.parent.height());
                    },
                    zoom: function(event, z) {
                        //event事件对象
                        //z缩放比率
                        if (this.scale >= this.maxscale && z > 1) return; //防止放大倍数超过10
                        var obj = $("img", this.img); //缩放针对的对象
                        var h = obj.height();
                        h *= z;
                        var w = obj.width();
                        w *= z;
                        if (h <= this.minpixel || w < this.minpixel) return; //防止任意一边的缩放后小于指定像素
                        //this.scale *= z;
                        var size = this.fixsize(w, h);
                        this.currentSize = size;
                        this.scale = this.currentSize.w / this.originalSize.w; //记录当前缩放比例
                        h = size.h;
                        w = size.w;
                        var top; //偏移后顶部位置
                        var left; //偏移后左侧位置
                        var positon = obj.offset(); //目标对象当前位置
                        left = positon.left;
                        top = positon.top;
                        //alert(left);

                        var offset = this.getOffset(event, obj); //鼠标相对于目标对象的偏移量
                        left += offset.x * (1 - z);
                        top += offset.y * (1 - z);
                        obj.height(h);
                        obj.width(w);
                        obj.offset({ top: top, left: left });
                    },
                    fixsize: function(w, h) {
                        var ratio = h / w;
                        var size = { w: w, h: h, ratio: ratio };
                        if (ratio != this.originalSize.ratio) {
                            size.w = w;
                            size.ratio = this.originalSize.ratio;
                            size.h = w * size.ratio;
                        }
                        return size;
                    },
                    getOffset: function(event, relative) {
                        // event 鼠标事件
                        // relative 想取得相对偏移量的对象
                        var e = event.pageX ? event : event.originalEvent;
                        var offset = { x: 0, y: 0 };
                        var targetPostion = relative.offset();
                        //var sourcePosition = $(event.target).offset();
                        var x = e.pageX ? e.pageX : e.clientX;
                        var y = e.pageY ? e.pageY : e.clientY;
                        offset.x = x - targetPostion.left;
                        offset.y = y - targetPostion.top;
                        //alert(offset.x);
                        return offset;
                    },
                    pan: function() {
                        //平移，支持两种模式
                        var p = $("img", this.img);
                        this.img.css("left", "0");
                        this.img.css("top", "0");
                        if (arguments.length == 1) {
                            var off = arguments[0];
                            p.offset(off);
                        }
                        if (arguments.length == 2) {
                            var dx, dy;
                            //dx 平移的x轴增量
                            //dy 平移的y轴增量
                            dx = arguments[0];
                            dy = arguments[1];

                            var off = p.offset();
                            off.left += dx;
                            off.top += dy;
                            p.offset(off);
                        }
                    },
                    reset: function() {
                        //恢复原状
                        var p = $("img", this.img);
                        p.css("left", "0");
                        p.css("top", "0");
                        p.width(this.originalSize.w);
                        p.height(this.originalSize.h);
                        this.scale = 1;
                        this.currentSize.w = this.originalSize.w;
                        this.currentSize.h = this.originalSize.h;
                        this.currentSize.ratio = this.originalSize.ratio;
                    }
                }
                $(this).data("ref", ref);
            });
        }
    });
})(jQuery);
